{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "有时，当调用代理时，您可能需要对其进行配置。这样做的例子包括配置要使用的LLM。下面，我们将通过一个例子来说明这一点。"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "afe59ed231a2f2b9"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[HumanMessage(content='hi', additional_kwargs={}, response_metadata={})]\n",
      "Hello! How can I assist you today?\n"
     ]
    },
    {
     "ename": "TypeError",
     "evalue": "unhashable type: 'list'",
     "output_type": "error",
     "traceback": [
      "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[0;31mTypeError\u001B[0m                                 Traceback (most recent call last)",
      "Cell \u001B[0;32mIn[20], line 31\u001B[0m\n\u001B[1;32m     29\u001B[0m workflow\u001B[38;5;241m.\u001B[39madd_edge(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmodel\u001B[39m\u001B[38;5;124m\"\u001B[39m,END)\n\u001B[1;32m     30\u001B[0m graph \u001B[38;5;241m=\u001B[39m workflow\u001B[38;5;241m.\u001B[39mcompile()\n\u001B[0;32m---> 31\u001B[0m graph\u001B[38;5;241m.\u001B[39minvoke({\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m: [HumanMessage(content\u001B[38;5;241m=\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mhi\u001B[39m\u001B[38;5;124m\"\u001B[39m)]})\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/__init__.py:1600\u001B[0m, in \u001B[0;36mPregel.invoke\u001B[0;34m(self, input, config, stream_mode, output_keys, interrupt_before, interrupt_after, debug, **kwargs)\u001B[0m\n\u001B[1;32m   1598\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m   1599\u001B[0m     chunks \u001B[38;5;241m=\u001B[39m []\n\u001B[0;32m-> 1600\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m chunk \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mstream(\n\u001B[1;32m   1601\u001B[0m     \u001B[38;5;28minput\u001B[39m,\n\u001B[1;32m   1602\u001B[0m     config,\n\u001B[1;32m   1603\u001B[0m     stream_mode\u001B[38;5;241m=\u001B[39mstream_mode,\n\u001B[1;32m   1604\u001B[0m     output_keys\u001B[38;5;241m=\u001B[39moutput_keys,\n\u001B[1;32m   1605\u001B[0m     interrupt_before\u001B[38;5;241m=\u001B[39minterrupt_before,\n\u001B[1;32m   1606\u001B[0m     interrupt_after\u001B[38;5;241m=\u001B[39minterrupt_after,\n\u001B[1;32m   1607\u001B[0m     debug\u001B[38;5;241m=\u001B[39mdebug,\n\u001B[1;32m   1608\u001B[0m     \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs,\n\u001B[1;32m   1609\u001B[0m ):\n\u001B[1;32m   1610\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m stream_mode \u001B[38;5;241m==\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mvalues\u001B[39m\u001B[38;5;124m\"\u001B[39m:\n\u001B[1;32m   1611\u001B[0m         latest \u001B[38;5;241m=\u001B[39m chunk\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/__init__.py:1328\u001B[0m, in \u001B[0;36mPregel.stream\u001B[0;34m(self, input, config, stream_mode, output_keys, interrupt_before, interrupt_after, debug, subgraphs)\u001B[0m\n\u001B[1;32m   1317\u001B[0m     \u001B[38;5;66;03m# Similarly to Bulk Synchronous Parallel / Pregel model\u001B[39;00m\n\u001B[1;32m   1318\u001B[0m     \u001B[38;5;66;03m# computation proceeds in steps, while there are channel updates\u001B[39;00m\n\u001B[1;32m   1319\u001B[0m     \u001B[38;5;66;03m# channel updates from step N are only visible in step N+1\u001B[39;00m\n\u001B[1;32m   1320\u001B[0m     \u001B[38;5;66;03m# channels are guaranteed to be immutable for the duration of the step,\u001B[39;00m\n\u001B[1;32m   1321\u001B[0m     \u001B[38;5;66;03m# with channel updates applied only at the transition between steps\u001B[39;00m\n\u001B[1;32m   1322\u001B[0m     \u001B[38;5;28;01mwhile\u001B[39;00m loop\u001B[38;5;241m.\u001B[39mtick(\n\u001B[1;32m   1323\u001B[0m         input_keys\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39minput_channels,\n\u001B[1;32m   1324\u001B[0m         interrupt_before\u001B[38;5;241m=\u001B[39minterrupt_before_,\n\u001B[1;32m   1325\u001B[0m         interrupt_after\u001B[38;5;241m=\u001B[39minterrupt_after_,\n\u001B[1;32m   1326\u001B[0m         manager\u001B[38;5;241m=\u001B[39mrun_manager,\n\u001B[1;32m   1327\u001B[0m     ):\n\u001B[0;32m-> 1328\u001B[0m         \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m runner\u001B[38;5;241m.\u001B[39mtick(\n\u001B[1;32m   1329\u001B[0m             loop\u001B[38;5;241m.\u001B[39mtasks\u001B[38;5;241m.\u001B[39mvalues(),\n\u001B[1;32m   1330\u001B[0m             timeout\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mstep_timeout,\n\u001B[1;32m   1331\u001B[0m             retry_policy\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mretry_policy,\n\u001B[1;32m   1332\u001B[0m             get_waiter\u001B[38;5;241m=\u001B[39mget_waiter,\n\u001B[1;32m   1333\u001B[0m         ):\n\u001B[1;32m   1334\u001B[0m             \u001B[38;5;66;03m# emit output\u001B[39;00m\n\u001B[1;32m   1335\u001B[0m             \u001B[38;5;28;01myield from\u001B[39;00m output()\n\u001B[1;32m   1336\u001B[0m \u001B[38;5;66;03m# emit output\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/runner.py:58\u001B[0m, in \u001B[0;36mPregelRunner.tick\u001B[0;34m(self, tasks, reraise, timeout, retry_policy, get_waiter)\u001B[0m\n\u001B[1;32m     56\u001B[0m t \u001B[38;5;241m=\u001B[39m tasks[\u001B[38;5;241m0\u001B[39m]\n\u001B[1;32m     57\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m---> 58\u001B[0m     run_with_retry(t, retry_policy)\n\u001B[1;32m     59\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mcommit(t, \u001B[38;5;28;01mNone\u001B[39;00m)\n\u001B[1;32m     60\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mException\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m exc:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/retry.py:29\u001B[0m, in \u001B[0;36mrun_with_retry\u001B[0;34m(task, retry_policy)\u001B[0m\n\u001B[1;32m     27\u001B[0m task\u001B[38;5;241m.\u001B[39mwrites\u001B[38;5;241m.\u001B[39mclear()\n\u001B[1;32m     28\u001B[0m \u001B[38;5;66;03m# run the task\u001B[39;00m\n\u001B[0;32m---> 29\u001B[0m task\u001B[38;5;241m.\u001B[39mproc\u001B[38;5;241m.\u001B[39minvoke(task\u001B[38;5;241m.\u001B[39minput, config)\n\u001B[1;32m     30\u001B[0m \u001B[38;5;66;03m# if successful, end\u001B[39;00m\n\u001B[1;32m     31\u001B[0m \u001B[38;5;28;01mbreak\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/utils/runnable.py:410\u001B[0m, in \u001B[0;36mRunnableSeq.invoke\u001B[0;34m(self, input, config, **kwargs)\u001B[0m\n\u001B[1;32m    408\u001B[0m context\u001B[38;5;241m.\u001B[39mrun(_set_config_context, config)\n\u001B[1;32m    409\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m i \u001B[38;5;241m==\u001B[39m \u001B[38;5;241m0\u001B[39m:\n\u001B[0;32m--> 410\u001B[0m     \u001B[38;5;28minput\u001B[39m \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(step\u001B[38;5;241m.\u001B[39minvoke, \u001B[38;5;28minput\u001B[39m, config, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[1;32m    411\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    412\u001B[0m     \u001B[38;5;28minput\u001B[39m \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(step\u001B[38;5;241m.\u001B[39minvoke, \u001B[38;5;28minput\u001B[39m, config)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/utils/runnable.py:184\u001B[0m, in \u001B[0;36mRunnableCallable.invoke\u001B[0;34m(self, input, config, **kwargs)\u001B[0m\n\u001B[1;32m    182\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    183\u001B[0m     context\u001B[38;5;241m.\u001B[39mrun(_set_config_context, config)\n\u001B[0;32m--> 184\u001B[0m     ret \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mfunc, \u001B[38;5;28minput\u001B[39m, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[1;32m    185\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(ret, Runnable) \u001B[38;5;129;01mand\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mrecurse:\n\u001B[1;32m    186\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m ret\u001B[38;5;241m.\u001B[39minvoke(\u001B[38;5;28minput\u001B[39m, config)\n",
      "Cell \u001B[0;32mIn[20], line 24\u001B[0m, in \u001B[0;36m_call_model\u001B[0;34m(state)\u001B[0m\n\u001B[1;32m     22\u001B[0m response \u001B[38;5;241m=\u001B[39m llm\u001B[38;5;241m.\u001B[39minvoke(state[\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m])\n\u001B[1;32m     23\u001B[0m \u001B[38;5;28mprint\u001B[39m(response)\n\u001B[0;32m---> 24\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m {\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m,[response]}\n",
      "\u001B[0;31mTypeError\u001B[0m: unhashable type: 'list'"
     ]
    }
   ],
   "source": [
    "\n",
    "from langchain_community.llms.tongyi import Tongyi\n",
    "from langgraph.constants import START,END\n",
    "from langgraph.graph import StateGraph\n",
    "from dotenv import load_dotenv\n",
    "import os\n",
    "from langchain_openai import ChatOpenAI\n",
    "import operator\n",
    "from langchain_core.messages import BaseMessage,HumanMessage\n",
    "from typing_extensions import TypedDict\n",
    "from typing import Annotated, Sequence\n",
    "\n",
    "load_dotenv()\n",
    "\n",
    "llm = Tongyi()\n",
    "\n",
    "class AgentState(TypedDict):\n",
    "    # add_messages函数定义了应该如何处理更新，operator.add表示“追加”或使用add_messages\n",
    "    messages: Annotated[Sequence[BaseMessage], operator.add]\n",
    "    \n",
    "def _call_model(state):\n",
    "    print(state[\"messages\"])\n",
    "    response = llm.invoke(state[\"messages\"])\n",
    "    print(response)\n",
    "    return {\"messages\",[response]}\n",
    "\n",
    "workflow = StateGraph(AgentState)\n",
    "workflow.add_node(\"model\",_call_model)\n",
    "workflow.add_edge(START,\"model\")\n",
    "workflow.add_edge(\"model\",END)\n",
    "graph = workflow.compile()\n",
    "graph.invoke({\"messages\": [HumanMessage(content=\"hi\")]})\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-11-04T07:19:42.368398Z",
     "start_time": "2024-11-04T07:19:40.722363Z"
    }
   },
   "id": "874722633cfb5bc2",
   "execution_count": 20
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Configure the graph\n",
    "让我们假设我们想扩展这个示例，让用户能够从多个LLM中进行选择。我们可以很容易地做到这一点，通过传入配置。任何配置信息都需要像下面这样，在可配置键中传递。这个配置是用来包含不属于输入的东西（因此，我们不希望将其作为状态的一部分进行跟踪）。\n",
    "\n",
    "微调_call_model增加RunnableConfig"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "37c5447af1fcd509"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "llm2 = ChatOpenAI(\n",
    "    openai_api_key=os.getenv(\"DASHSCOPE_API_KEY\"),\n",
    "    openai_api_base=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n",
    "    model_name=\"qwen-max\",\n",
    "    temperature=0, streaming=True,\n",
    ")\n",
    "\n",
    "models = {\n",
    "    \"llm\":llm,\n",
    "    \"llm2\":llm2\n",
    "}\n",
    "\n",
    "def _call_model(state,config):\n",
    "    # 获取配置的model，未配置时，默认为llm\n",
    "    model_name = config[\"configurable\"].get(\"model\",\"llm\")\n",
    "    model = models[model_name]\n",
    "    response = model.invoke(state[\"messages\"])\n",
    "    return {\"messages\",[response]}\n",
    "\n",
    "workflow2 = StateGraph(AgentState)\n",
    "workflow2.add_node(\"model\",_call_model)\n",
    "workflow2.add_edge(START,\"model\")\n",
    "workflow2.add_edge(\"model\",END)\n",
    "graph2 = workflow2.compile()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-11-04T07:06:08.105667Z",
     "start_time": "2024-11-04T07:06:08.012564Z"
    }
   },
   "id": "cde25c7db42a095c",
   "execution_count": 4
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "unhashable type: 'list'",
     "output_type": "error",
     "traceback": [
      "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[0;31mTypeError\u001B[0m                                 Traceback (most recent call last)",
      "Cell \u001B[0;32mIn[5], line 3\u001B[0m\n\u001B[1;32m      1\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01mlangchain_core\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mmessages\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m HumanMessage\n\u001B[0;32m----> 3\u001B[0m graph2\u001B[38;5;241m.\u001B[39minvoke({\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m: [HumanMessage(content\u001B[38;5;241m=\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mhi\u001B[39m\u001B[38;5;124m\"\u001B[39m)]})\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/__init__.py:1600\u001B[0m, in \u001B[0;36mPregel.invoke\u001B[0;34m(self, input, config, stream_mode, output_keys, interrupt_before, interrupt_after, debug, **kwargs)\u001B[0m\n\u001B[1;32m   1598\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m   1599\u001B[0m     chunks \u001B[38;5;241m=\u001B[39m []\n\u001B[0;32m-> 1600\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m chunk \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mstream(\n\u001B[1;32m   1601\u001B[0m     \u001B[38;5;28minput\u001B[39m,\n\u001B[1;32m   1602\u001B[0m     config,\n\u001B[1;32m   1603\u001B[0m     stream_mode\u001B[38;5;241m=\u001B[39mstream_mode,\n\u001B[1;32m   1604\u001B[0m     output_keys\u001B[38;5;241m=\u001B[39moutput_keys,\n\u001B[1;32m   1605\u001B[0m     interrupt_before\u001B[38;5;241m=\u001B[39minterrupt_before,\n\u001B[1;32m   1606\u001B[0m     interrupt_after\u001B[38;5;241m=\u001B[39minterrupt_after,\n\u001B[1;32m   1607\u001B[0m     debug\u001B[38;5;241m=\u001B[39mdebug,\n\u001B[1;32m   1608\u001B[0m     \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs,\n\u001B[1;32m   1609\u001B[0m ):\n\u001B[1;32m   1610\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m stream_mode \u001B[38;5;241m==\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mvalues\u001B[39m\u001B[38;5;124m\"\u001B[39m:\n\u001B[1;32m   1611\u001B[0m         latest \u001B[38;5;241m=\u001B[39m chunk\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/__init__.py:1328\u001B[0m, in \u001B[0;36mPregel.stream\u001B[0;34m(self, input, config, stream_mode, output_keys, interrupt_before, interrupt_after, debug, subgraphs)\u001B[0m\n\u001B[1;32m   1317\u001B[0m     \u001B[38;5;66;03m# Similarly to Bulk Synchronous Parallel / Pregel model\u001B[39;00m\n\u001B[1;32m   1318\u001B[0m     \u001B[38;5;66;03m# computation proceeds in steps, while there are channel updates\u001B[39;00m\n\u001B[1;32m   1319\u001B[0m     \u001B[38;5;66;03m# channel updates from step N are only visible in step N+1\u001B[39;00m\n\u001B[1;32m   1320\u001B[0m     \u001B[38;5;66;03m# channels are guaranteed to be immutable for the duration of the step,\u001B[39;00m\n\u001B[1;32m   1321\u001B[0m     \u001B[38;5;66;03m# with channel updates applied only at the transition between steps\u001B[39;00m\n\u001B[1;32m   1322\u001B[0m     \u001B[38;5;28;01mwhile\u001B[39;00m loop\u001B[38;5;241m.\u001B[39mtick(\n\u001B[1;32m   1323\u001B[0m         input_keys\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39minput_channels,\n\u001B[1;32m   1324\u001B[0m         interrupt_before\u001B[38;5;241m=\u001B[39minterrupt_before_,\n\u001B[1;32m   1325\u001B[0m         interrupt_after\u001B[38;5;241m=\u001B[39minterrupt_after_,\n\u001B[1;32m   1326\u001B[0m         manager\u001B[38;5;241m=\u001B[39mrun_manager,\n\u001B[1;32m   1327\u001B[0m     ):\n\u001B[0;32m-> 1328\u001B[0m         \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m runner\u001B[38;5;241m.\u001B[39mtick(\n\u001B[1;32m   1329\u001B[0m             loop\u001B[38;5;241m.\u001B[39mtasks\u001B[38;5;241m.\u001B[39mvalues(),\n\u001B[1;32m   1330\u001B[0m             timeout\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mstep_timeout,\n\u001B[1;32m   1331\u001B[0m             retry_policy\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mretry_policy,\n\u001B[1;32m   1332\u001B[0m             get_waiter\u001B[38;5;241m=\u001B[39mget_waiter,\n\u001B[1;32m   1333\u001B[0m         ):\n\u001B[1;32m   1334\u001B[0m             \u001B[38;5;66;03m# emit output\u001B[39;00m\n\u001B[1;32m   1335\u001B[0m             \u001B[38;5;28;01myield from\u001B[39;00m output()\n\u001B[1;32m   1336\u001B[0m \u001B[38;5;66;03m# emit output\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/runner.py:58\u001B[0m, in \u001B[0;36mPregelRunner.tick\u001B[0;34m(self, tasks, reraise, timeout, retry_policy, get_waiter)\u001B[0m\n\u001B[1;32m     56\u001B[0m t \u001B[38;5;241m=\u001B[39m tasks[\u001B[38;5;241m0\u001B[39m]\n\u001B[1;32m     57\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m---> 58\u001B[0m     run_with_retry(t, retry_policy)\n\u001B[1;32m     59\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mcommit(t, \u001B[38;5;28;01mNone\u001B[39;00m)\n\u001B[1;32m     60\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mException\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m exc:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/retry.py:29\u001B[0m, in \u001B[0;36mrun_with_retry\u001B[0;34m(task, retry_policy)\u001B[0m\n\u001B[1;32m     27\u001B[0m task\u001B[38;5;241m.\u001B[39mwrites\u001B[38;5;241m.\u001B[39mclear()\n\u001B[1;32m     28\u001B[0m \u001B[38;5;66;03m# run the task\u001B[39;00m\n\u001B[0;32m---> 29\u001B[0m task\u001B[38;5;241m.\u001B[39mproc\u001B[38;5;241m.\u001B[39minvoke(task\u001B[38;5;241m.\u001B[39minput, config)\n\u001B[1;32m     30\u001B[0m \u001B[38;5;66;03m# if successful, end\u001B[39;00m\n\u001B[1;32m     31\u001B[0m \u001B[38;5;28;01mbreak\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/utils/runnable.py:410\u001B[0m, in \u001B[0;36mRunnableSeq.invoke\u001B[0;34m(self, input, config, **kwargs)\u001B[0m\n\u001B[1;32m    408\u001B[0m context\u001B[38;5;241m.\u001B[39mrun(_set_config_context, config)\n\u001B[1;32m    409\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m i \u001B[38;5;241m==\u001B[39m \u001B[38;5;241m0\u001B[39m:\n\u001B[0;32m--> 410\u001B[0m     \u001B[38;5;28minput\u001B[39m \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(step\u001B[38;5;241m.\u001B[39minvoke, \u001B[38;5;28minput\u001B[39m, config, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[1;32m    411\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    412\u001B[0m     \u001B[38;5;28minput\u001B[39m \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(step\u001B[38;5;241m.\u001B[39minvoke, \u001B[38;5;28minput\u001B[39m, config)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/utils/runnable.py:184\u001B[0m, in \u001B[0;36mRunnableCallable.invoke\u001B[0;34m(self, input, config, **kwargs)\u001B[0m\n\u001B[1;32m    182\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    183\u001B[0m     context\u001B[38;5;241m.\u001B[39mrun(_set_config_context, config)\n\u001B[0;32m--> 184\u001B[0m     ret \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mfunc, \u001B[38;5;28minput\u001B[39m, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[1;32m    185\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(ret, Runnable) \u001B[38;5;129;01mand\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mrecurse:\n\u001B[1;32m    186\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m ret\u001B[38;5;241m.\u001B[39minvoke(\u001B[38;5;28minput\u001B[39m, config)\n",
      "Cell \u001B[0;32mIn[4], line 18\u001B[0m, in \u001B[0;36m_call_model\u001B[0;34m(state, config)\u001B[0m\n\u001B[1;32m     16\u001B[0m model \u001B[38;5;241m=\u001B[39m models[model_name]\n\u001B[1;32m     17\u001B[0m response \u001B[38;5;241m=\u001B[39m model\u001B[38;5;241m.\u001B[39minvoke(state[\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m])\n\u001B[0;32m---> 18\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m {\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m,[response]}\n",
      "\u001B[0;31mTypeError\u001B[0m: unhashable type: 'list'"
     ]
    }
   ],
   "source": [
    "from langchain_core.messages import HumanMessage\n",
    "\n",
    "graph2.invoke({\"messages\": [HumanMessage(content=\"hi\")]})\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-11-04T07:06:12.297550Z",
     "start_time": "2024-11-04T07:06:10.401864Z"
    }
   },
   "id": "e1b99dd3dd99046f",
   "execution_count": 5
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "unhashable type: 'list'",
     "output_type": "error",
     "traceback": [
      "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[0;31mTypeError\u001B[0m                                 Traceback (most recent call last)",
      "Cell \u001B[0;32mIn[22], line 2\u001B[0m\n\u001B[1;32m      1\u001B[0m config \u001B[38;5;241m=\u001B[39m {\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mconfigurable\u001B[39m\u001B[38;5;124m\"\u001B[39m: {\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124msystem_message\u001B[39m\u001B[38;5;124m\"\u001B[39m: \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mrespond in italian\u001B[39m\u001B[38;5;124m\"\u001B[39m}}\n\u001B[0;32m----> 2\u001B[0m graph2\u001B[38;5;241m.\u001B[39minvoke({\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m: [HumanMessage(content\u001B[38;5;241m=\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mhi\u001B[39m\u001B[38;5;124m\"\u001B[39m)]}, config\u001B[38;5;241m=\u001B[39mconfig)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/__init__.py:1600\u001B[0m, in \u001B[0;36mPregel.invoke\u001B[0;34m(self, input, config, stream_mode, output_keys, interrupt_before, interrupt_after, debug, **kwargs)\u001B[0m\n\u001B[1;32m   1598\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m   1599\u001B[0m     chunks \u001B[38;5;241m=\u001B[39m []\n\u001B[0;32m-> 1600\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m chunk \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mstream(\n\u001B[1;32m   1601\u001B[0m     \u001B[38;5;28minput\u001B[39m,\n\u001B[1;32m   1602\u001B[0m     config,\n\u001B[1;32m   1603\u001B[0m     stream_mode\u001B[38;5;241m=\u001B[39mstream_mode,\n\u001B[1;32m   1604\u001B[0m     output_keys\u001B[38;5;241m=\u001B[39moutput_keys,\n\u001B[1;32m   1605\u001B[0m     interrupt_before\u001B[38;5;241m=\u001B[39minterrupt_before,\n\u001B[1;32m   1606\u001B[0m     interrupt_after\u001B[38;5;241m=\u001B[39minterrupt_after,\n\u001B[1;32m   1607\u001B[0m     debug\u001B[38;5;241m=\u001B[39mdebug,\n\u001B[1;32m   1608\u001B[0m     \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs,\n\u001B[1;32m   1609\u001B[0m ):\n\u001B[1;32m   1610\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m stream_mode \u001B[38;5;241m==\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mvalues\u001B[39m\u001B[38;5;124m\"\u001B[39m:\n\u001B[1;32m   1611\u001B[0m         latest \u001B[38;5;241m=\u001B[39m chunk\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/__init__.py:1328\u001B[0m, in \u001B[0;36mPregel.stream\u001B[0;34m(self, input, config, stream_mode, output_keys, interrupt_before, interrupt_after, debug, subgraphs)\u001B[0m\n\u001B[1;32m   1317\u001B[0m     \u001B[38;5;66;03m# Similarly to Bulk Synchronous Parallel / Pregel model\u001B[39;00m\n\u001B[1;32m   1318\u001B[0m     \u001B[38;5;66;03m# computation proceeds in steps, while there are channel updates\u001B[39;00m\n\u001B[1;32m   1319\u001B[0m     \u001B[38;5;66;03m# channel updates from step N are only visible in step N+1\u001B[39;00m\n\u001B[1;32m   1320\u001B[0m     \u001B[38;5;66;03m# channels are guaranteed to be immutable for the duration of the step,\u001B[39;00m\n\u001B[1;32m   1321\u001B[0m     \u001B[38;5;66;03m# with channel updates applied only at the transition between steps\u001B[39;00m\n\u001B[1;32m   1322\u001B[0m     \u001B[38;5;28;01mwhile\u001B[39;00m loop\u001B[38;5;241m.\u001B[39mtick(\n\u001B[1;32m   1323\u001B[0m         input_keys\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39minput_channels,\n\u001B[1;32m   1324\u001B[0m         interrupt_before\u001B[38;5;241m=\u001B[39minterrupt_before_,\n\u001B[1;32m   1325\u001B[0m         interrupt_after\u001B[38;5;241m=\u001B[39minterrupt_after_,\n\u001B[1;32m   1326\u001B[0m         manager\u001B[38;5;241m=\u001B[39mrun_manager,\n\u001B[1;32m   1327\u001B[0m     ):\n\u001B[0;32m-> 1328\u001B[0m         \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m runner\u001B[38;5;241m.\u001B[39mtick(\n\u001B[1;32m   1329\u001B[0m             loop\u001B[38;5;241m.\u001B[39mtasks\u001B[38;5;241m.\u001B[39mvalues(),\n\u001B[1;32m   1330\u001B[0m             timeout\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mstep_timeout,\n\u001B[1;32m   1331\u001B[0m             retry_policy\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mretry_policy,\n\u001B[1;32m   1332\u001B[0m             get_waiter\u001B[38;5;241m=\u001B[39mget_waiter,\n\u001B[1;32m   1333\u001B[0m         ):\n\u001B[1;32m   1334\u001B[0m             \u001B[38;5;66;03m# emit output\u001B[39;00m\n\u001B[1;32m   1335\u001B[0m             \u001B[38;5;28;01myield from\u001B[39;00m output()\n\u001B[1;32m   1336\u001B[0m \u001B[38;5;66;03m# emit output\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/runner.py:58\u001B[0m, in \u001B[0;36mPregelRunner.tick\u001B[0;34m(self, tasks, reraise, timeout, retry_policy, get_waiter)\u001B[0m\n\u001B[1;32m     56\u001B[0m t \u001B[38;5;241m=\u001B[39m tasks[\u001B[38;5;241m0\u001B[39m]\n\u001B[1;32m     57\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m---> 58\u001B[0m     run_with_retry(t, retry_policy)\n\u001B[1;32m     59\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mcommit(t, \u001B[38;5;28;01mNone\u001B[39;00m)\n\u001B[1;32m     60\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mException\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m exc:\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/pregel/retry.py:29\u001B[0m, in \u001B[0;36mrun_with_retry\u001B[0;34m(task, retry_policy)\u001B[0m\n\u001B[1;32m     27\u001B[0m task\u001B[38;5;241m.\u001B[39mwrites\u001B[38;5;241m.\u001B[39mclear()\n\u001B[1;32m     28\u001B[0m \u001B[38;5;66;03m# run the task\u001B[39;00m\n\u001B[0;32m---> 29\u001B[0m task\u001B[38;5;241m.\u001B[39mproc\u001B[38;5;241m.\u001B[39minvoke(task\u001B[38;5;241m.\u001B[39minput, config)\n\u001B[1;32m     30\u001B[0m \u001B[38;5;66;03m# if successful, end\u001B[39;00m\n\u001B[1;32m     31\u001B[0m \u001B[38;5;28;01mbreak\u001B[39;00m\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/utils/runnable.py:410\u001B[0m, in \u001B[0;36mRunnableSeq.invoke\u001B[0;34m(self, input, config, **kwargs)\u001B[0m\n\u001B[1;32m    408\u001B[0m context\u001B[38;5;241m.\u001B[39mrun(_set_config_context, config)\n\u001B[1;32m    409\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m i \u001B[38;5;241m==\u001B[39m \u001B[38;5;241m0\u001B[39m:\n\u001B[0;32m--> 410\u001B[0m     \u001B[38;5;28minput\u001B[39m \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(step\u001B[38;5;241m.\u001B[39minvoke, \u001B[38;5;28minput\u001B[39m, config, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[1;32m    411\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    412\u001B[0m     \u001B[38;5;28minput\u001B[39m \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(step\u001B[38;5;241m.\u001B[39minvoke, \u001B[38;5;28minput\u001B[39m, config)\n",
      "File \u001B[0;32m/opt/anaconda3/envs/ai_312/lib/python3.12/site-packages/langgraph/utils/runnable.py:184\u001B[0m, in \u001B[0;36mRunnableCallable.invoke\u001B[0;34m(self, input, config, **kwargs)\u001B[0m\n\u001B[1;32m    182\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m    183\u001B[0m     context\u001B[38;5;241m.\u001B[39mrun(_set_config_context, config)\n\u001B[0;32m--> 184\u001B[0m     ret \u001B[38;5;241m=\u001B[39m context\u001B[38;5;241m.\u001B[39mrun(\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mfunc, \u001B[38;5;28minput\u001B[39m, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[1;32m    185\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(ret, Runnable) \u001B[38;5;129;01mand\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mrecurse:\n\u001B[1;32m    186\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m ret\u001B[38;5;241m.\u001B[39minvoke(\u001B[38;5;28minput\u001B[39m, config)\n",
      "Cell \u001B[0;32mIn[4], line 18\u001B[0m, in \u001B[0;36m_call_model\u001B[0;34m(state, config)\u001B[0m\n\u001B[1;32m     16\u001B[0m model \u001B[38;5;241m=\u001B[39m models[model_name]\n\u001B[1;32m     17\u001B[0m response \u001B[38;5;241m=\u001B[39m model\u001B[38;5;241m.\u001B[39minvoke(state[\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m])\n\u001B[0;32m---> 18\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m {\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmessages\u001B[39m\u001B[38;5;124m\"\u001B[39m,[response]}\n",
      "\u001B[0;31mTypeError\u001B[0m: unhashable type: 'list'"
     ]
    }
   ],
   "source": [
    "config = {\"configurable\": {\"system_message\": \"respond in italian\"}}\n",
    "graph2.invoke({\"messages\": [HumanMessage(content=\"hi\")]}, config=config)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-11-04T07:22:10.374734Z",
     "start_time": "2024-11-04T07:22:08.800409Z"
    }
   },
   "id": "2a21c4cb68786223",
   "execution_count": 22
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
